home *** CD-ROM | disk | FTP | other *** search
/ Windows News 2010 Summer - Disc 1 / WN_Ete2010_CD1.iso / Onglet5 / Weezo / Weezo setup.exe / {code_appDir} / www / ext / videoIPhone.php < prev   
PHP Script  |  2010-05-19  |  7KB  |  240 lines

  1. <?php
  2. /*
  3.  * iPod / iPhone / iPad video streaming
  4.  * Included by video.php
  5.  * Parameters:
  6.  *     array $uri: parsed video parameters
  7.  *    string $completeFilename: video (decoded) source file name, access rights checked
  8.  *
  9.  
  10.  *
  11.  * PHP version 5
  12.  *
  13.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  14.  * that is available through the world-wide-web at the following URI:
  15.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  16.  * the PHP License and are unable to obtain it through the web, please
  17.  * send a note to license@php.net so we can mail you a copy immediately.
  18.  *
  19.  * @category   NA
  20.  * @package    NA
  21.  * @author     Nicolas Bruley / Peer 2 World <contact@weezo.net>
  22.  * @copyright  2005-2009 Nicolas Bruley / Peer 2 World
  23.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  24.  * @version    CVS: $Id:$
  25.  * @link       http://www.weezo.net
  26.  * @since      File available since Release 1.0.0
  27.  */
  28.  
  29. define('M3U8NL',"\n");
  30.  
  31. /**
  32.  * URL rewriting: convert back shortened URL (from m3u8 file) to standard video parameters encoded URL
  33.  */
  34. function vIPodRewriteURL(){
  35.     global $completeFilename;
  36.     global $uri;
  37.  
  38.     wSession_start_nowrite();
  39.  
  40.     // Retreive / set session Id
  41.     $_SESSION['activeResourceId']=$_GET['resId'];
  42.  
  43.     // Restore stream parameters (filename & bitrate)
  44.     if(!($completeFilename=cfRGetVar('videoIPhoneCompleteFilename'))) die();
  45.  
  46.     $uri['format']='ts';
  47.     $uri['bandwidth']=cfRGetVar('videoIPhoneBandwidth');
  48.     $uri['offset']=(int)@$_GET['offset'];
  49. }
  50.  
  51. /**
  52.  * @desc Send M3U8 Stream Alternates file with links to M3U8 files for available reencoding bandwidths
  53.  * (not used as iPhone starts with the lowest bandwidth and would skip to upper one only at end of 1st segment... but as segments are not used, it wouldn't work)
  54.  *
  55.  */
  56. function vIPodM3UStreamAlternates(){
  57.     global $completeFilename;
  58.     global $bandwidths;
  59.  
  60.     // m3u8 content-type header
  61.     WHeaders::contentType('foo.m3u8');
  62.  
  63.     // Start output buffering to satisfy potential HTTP Range request
  64.     cfRangeAccessibleOutputStart();
  65. //$_SERVER['REQUEST_URI']=substr($_SERVER['REQUEST_URI'],1).'.m3u8';
  66.     echo "#EXTM3U".M3U8NL;
  67.  
  68.     // Lowest bitrate
  69.     echo "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=".$bandwidths['low']."000".M3U8NL;
  70.     echo str_replace('.m3u8sa','.m3u8/bandwidth.low',$_SERVER['REQUEST_URI']).M3U8NL;
  71.  
  72.     // Max output size
  73.     $os=cfRGetVar('flashOutputSize'); if($os=='original') $os=9999;
  74.  
  75.     // Intermediate bitrate
  76.     if($os>160 && cfRGetVar('flashOutputQuality')!='low'){
  77.         echo "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=".$bandwidths['medium']."000".M3U8NL;
  78.         echo str_replace('.m3u8sa','.m3u8/bandwidth.medium',$_SERVER['REQUEST_URI']).M3U8NL;
  79.  
  80.         // High bitrate
  81.         if($os>320 && cfRGetVar('flashOutputQuality')!='medium'){
  82.             echo "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=".$bandwidths['high']."000".M3U8NL;
  83.             echo str_replace('.m3u8sa','.m3u8/bandwidth.high',$_SERVER['REQUEST_URI']).M3U8NL;
  84.         }
  85.     }
  86.  
  87.     // Send output
  88.     cfRangeAccessibleOutputSend();
  89.     exit;
  90. }
  91.  
  92. /**
  93.  * @desc Send M3U file splitting video into segments
  94.  *
  95.  */
  96. function vIPodM3U(){
  97.     global $completeFilename;
  98.     global $uri;
  99.     global $bandwidths;
  100.  
  101.     // Get kbps bandwidth from low/medium/high
  102.     $bandwidth=@$bandwidths[$uri['bandwidth']]; if(!$bandwidth) $bandwidth=$bandwidths['low'];
  103.  
  104.     // Store stream parameters so they can be restored after URL rewritting
  105.     cfRSetVar('videoIPhoneCompleteFilename',$completeFilename);
  106.     cfRSetVar('videoIPhoneBandwidth',$bandwidth);
  107.  
  108.  
  109.     cfRangeAccessibleOutputStart();
  110.  
  111.     // Get video duration
  112.     require_once(INCLUDE_DIR.'viewVideoFunctions.php');
  113.     $t=vvfVideoDuration($completeFilename);
  114.     if(!$t) $t=3600*4;
  115.  
  116.     // Compute segments length
  117.     $int=max(3,min(10,$t/100));
  118.  
  119.     $nb=ceil($t/$int);
  120.  
  121.  
  122.     // m3u8 content-type header
  123.     WHeaders::contentType('foo.m3u8');
  124.  
  125.     // Send M3U8 segments file
  126.     echo "#EXTM3U".M3U8NL;
  127.     echo "#EXT-X-MEDIA-SEQUENCE:0".M3U8NL;
  128.     echo "#EXT-X-TARGETDURATION:$int".M3U8NL;
  129.  
  130.     // Generate segment links
  131.     for($i=1;$i<$nb;$i++){
  132.         echo "#EXTINF:$int,".M3U8NL;
  133.         // Use shortened URL, to reduce overall size. URL will be converted back with apache rewriting and vIPodRewriteURL()
  134.         echo "/ext/".$uri['resId'].'.'.($i*$int).".ts".M3U8NL;
  135.     }
  136.     echo '#EXT-X-ENDLIST';
  137.  
  138.     cfRangeAccessibleOutputSend();
  139.     exit;
  140. }
  141.  
  142. /**
  143.  * @desc Reencode video and sent to output
  144.  *
  145.  */
  146. function vIPodVideo(){
  147.     global $completeFilename;
  148.     global $bandwidths;
  149.     global $uri;
  150.  
  151.     require_once(INCLUDE_DIR.'viewVideoFunctions.php');
  152.  
  153.     // Get video dimensions
  154.     list($sw,$sh)=vvfVideoDimensions($completeFilename);
  155.  
  156.     // Adapt dimension to iPhone viewport size
  157.     list($w,$h)=cfThumbnailDimensions($sw,$sh,480,320);
  158.  
  159.     // Compute audio & video bitrate
  160.     switch ($uri['bandwidth']){
  161.         case $bandwidths['low']:
  162.             $vbr=96;
  163.             $abr=48;
  164.             $w/=2;
  165.             $h/=2;
  166.             $audioChannels=1;
  167.             break;
  168.         case $bandwidths['medium']:
  169.             $vbr=128;
  170.             $abr=48;
  171.             $audioChannels=1;
  172.             break;
  173.         case $bandwidths['high']:
  174.             $vbr=512;
  175.             $abr=64;
  176.             $audioChannels=2;
  177.             break;
  178.     }
  179.     // mkv are likely to contain 6 channels AC3, that can't be reencoded to single channel
  180.     if($audioChannels==1 && cfFileExtension($completeFilename)=='mkv') $audioChannels=2;
  181.  
  182.     // Offset
  183.     if(!isset($uri['offset'])) $uri['offset']=0;
  184.  
  185.     // Set Width & Height multiple of 16 (needed for optimal encoding)
  186.     $w=16*round($w/16);
  187.     $h=16*round($h/16);
  188.  
  189.     // Use ffmpeg to reencode
  190.     $cl='"'.cfFfmpegExe().'" -re -redelay 9 -ss '.((int)$uri['offset']).' -i  "'.$completeFilename.'" -f mpegts -acodec libmp3lame -async 1 -ab '.$abr.'k -ac '.$audioChannels.' -s '.$w.'x'.$h.' -vcodec libx264 -b '.$vbr.'k -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -subq 5 -trellis 1 -refs 1 -coder 0 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 200k -maxrate '.$vbr.'k -bufsize '.$vbr.'k -rc_eq \'blurCplx^(1-qComp)\' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect '.$w.':'.$h.' -g 30 -async 2 -';
  191.     //cfDbg($cl);
  192.  
  193.     header('Content-Type: video/MP2T');
  194.     header('Accept-Ranges: byte');
  195.  
  196.     // If bytes range requested
  197.     $h=getallheaders();
  198.     if(isset($h['Range'])) {
  199.         header('HTTP/1.1 206 Partial Content');
  200.         //cfDebugSingle($uri['offset'].'=>'.$h['Range']);
  201.  
  202.         $h['Range']=substr($h['Range'],6);
  203.         list($from,$to)=explode('-',$h['Range']);
  204.  
  205.         header("Content-Range: bytes $from-$to/9999999999");
  206.         header("Content-Length: ".($to-$from));
  207.  
  208.         if($to==1) die('G'); // opt: if 1st byte only requested, don't bother with ffmpeg
  209.         cfStreamProc($cl,array('stdout'=>'stdout'),array('range'=>array('from'=>$from, 'to'=>$to)));
  210.     }
  211.     // All content requested (no HTTP Range)
  212.     else{
  213.         header("Content-Length: 999999999");
  214.  
  215.         cfStreamProc($cl,array('stdout'=>'stdout'));
  216.     }
  217.     exit;
  218. }
  219.  
  220. $bandwidths=array('low'=>96,'medium'=>256,'high'=>384);
  221.  
  222. // URL rewriting: convert back shortened URL (from m3u8 file) to standard video parameters encoded URL
  223. if(isset($_GET['resId']) && isset($_GET['offset'])) vIPodRewriteURL();
  224.  
  225. // Else, verify script has been included by video.php
  226. if(!isset($completeFilename) || !isset($uri['format'])) die();
  227.  
  228. // Serve content depending on requested format
  229. switch ($uri['format']){
  230.     // Stream Alternates (Bitrate) m3u8 file
  231.     case 'm3u8sa'; vIPodM3UStreamAlternates();
  232.  
  233.     // m3u8 file for given bitrate
  234.     case 'm3u8'; vIPodM3U();
  235.  
  236.     // video
  237.     case 'ts'; vIPodVideo();
  238. }
  239.  
  240.